package com.yiyuan.app.service.impl;

import com.guaike.core.entity.enums.EnableStatusEnum;
import com.guaike.core.entity.result.Result;
import com.guaike.core.redis.context.ApiContext;
import com.guaike.core.utils.DateUtil;
import com.guaike.core.utils.ListUtil;
import com.yiyuan.app.dao.*;
import com.yiyuan.app.entity.enums.*;
import com.yiyuan.app.entity.param.BoxDTO;
import com.yiyuan.app.entity.po.*;
import com.yiyuan.app.entity.result.*;
import com.yiyuan.app.service.RechargeService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.*;

@Slf4j
@Service
@AllArgsConstructor
public class RechargeServiceImpl implements RechargeService {

    private final MProductPackageDAO mProductPackageDAO;
    private final MProductCardDAO mProductCardDAO;
    private final MProductCardDetailDAO mProductCardDetailDAO;
    private final MRecordProductCardDAO mRecordProductCardDAO;
    private final MProductSeriesRechargeDAO mProductSeriesRechargeDAO;
    private final MProductSeriesRechargeDaysDAO mProductSeriesRechargeDaysDAO;
    private final MProductSeriesRechargeBoxDAO mProductSeriesRechargeBoxDAO;
    private final MRecordSeriesRechargeDetailDAO mRecordSeriesRechargeDetailDAO;
    private final MRecordSeriesRechargeDAO mRecordSeriesRechargeDAO;
    private final MProductLookDAO mProductLookDAO;
    private final MProductLookDetailDAO mProductLookDetailDAO;
    private final UAppUserEquityDAO uAppUserEquityDAO;
    private final MProductOccupyDAO mProductOccupyDAO;
    private final DDetailsPineconeDAO dDetailsPineconeDAO;

    @Override
    public Result<List<RechargeActivityVO>> activityList() {
        List<MProductPackagePO> pos = mProductPackageDAO.findRechargeActivity();
        List<RechargeActivityVO> list = ListUtil.copyList(pos, RechargeActivityVO.class);
        return Result.success().data(list).build();
    }

    @Override
    public Result<List<ProductOccupyVO>> occupyList() {
        List<MProductOccupyPO> pos = mProductOccupyDAO.findList(MProductOccupyPO::getStatus, EnableStatusEnum.ENABLE.getCode(), MProductOccupyPO::getDuration, Boolean.TRUE);
        List<ProductOccupyVO> list = ListUtil.copyList(pos, ProductOccupyVO.class);
        return Result.success().data(list).build();
    }

    @Override
    public Result<List<ProductCardVO>> productCardList() {
        AppUser currentUser = ApiContext.getCurrentUser();
        List<MProductCardPO> pos = mProductCardDAO.findList(MProductCardPO::getStatus, EnableStatusEnum.ENABLE.getCode(), MProductCardPO::getProductType, Boolean.TRUE);
        List<ProductCardVO> list = new ArrayList<>();
        pos.forEach(po -> {
            ProductCardVO vo = new ProductCardVO();
            vo.setProductName(po.getProductName());
            vo.setProductType(po.getProductType());
            List<MProductCardDetailPO> cardPOS = mProductCardDetailDAO.findList(MProductCardDetailPO::getProductCardId, po.getId(), MProductCardDetailPO::getCardType, Boolean.TRUE);
            List<ProductCardDetailVO> cardVOS = new ArrayList<>();
            cardPOS.forEach(cardPO -> {
                ProductCardDetailVO cardDetailVO = new ProductCardDetailVO();
                BeanUtils.copyProperties(cardPO, cardDetailVO);
                if (CardTypeEnum.week_card.getCode().equals(cardPO.getCardType())) {
                    cardDetailVO.setTotalPinecone(Math.addExact(cardPO.getDirectlyPinecone(), Math.multiplyExact(cardPO.getDailyPinecone(), 7)));
                } else {
                    cardDetailVO.setTotalPinecone(Math.addExact(cardPO.getDirectlyPinecone(), Math.multiplyExact(cardPO.getDailyPinecone(), 30)));
                }
                MRecordProductCardPO card = mRecordProductCardDAO.findUserCardByCardId(currentUser.getUserId(), cardPO.getId());
                if (Objects.nonNull(card)) {
                    cardDetailVO.setRemainDay(card.getRemainDay());
                }
                cardVOS.add(cardDetailVO);
            });
            vo.setCardVOS(cardVOS);
            list.add(vo);
        });
        return Result.success().data(list).build();
    }

    @Override
    public Result<RechargeSeriesVO> seriesRechargeList() {
        MProductSeriesRechargePO rechargePO = mProductSeriesRechargeDAO.findOne(MProductSeriesRechargePO::getStatus, EnableStatusEnum.ENABLE.getCode());
        if (Objects.isNull(rechargePO)) {
            return Result.failure().message("每日续航维护中").build();
        }
        AppUser currentUser = ApiContext.getCurrentUser();
        RechargeSeriesVO result = new RechargeSeriesVO();
        List<MProductSeriesRechargeDaysPO> daysPOS = mProductSeriesRechargeDaysDAO.findAll(MProductSeriesRechargeDaysPO::getSeriesDays, Boolean.TRUE);
        MRecordSeriesRechargePO latestOne = mRecordSeriesRechargeDAO.findLatestOne(currentUser.getUserId());
        if (Objects.isNull(latestOne)) {
            MProductSeriesRechargeDaysPO daysPO = mProductSeriesRechargeDaysDAO.findOne(MProductSeriesRechargeDaysPO::getSeriesDays, 1);
            result.setId(daysPO.getId());
            result.setDay(1);
            result.setMoney(daysPO.getMoney());
        } else {
            MRecordSeriesRechargeDetailPO detailPO = mRecordSeriesRechargeDetailDAO.findLatestAlreadyRecharge(currentUser.getUserId(), latestOne.getId());
            if (DateUtil.days(detailPO.getCreateTime().toLocalDate(), LocalDate.now()) == 1) {
                MProductSeriesRechargeDaysPO daysPO;
                if (detailPO.getRechargeDay() == 7) {
                    daysPO = mProductSeriesRechargeDaysDAO.findOne(MProductSeriesRechargeDaysPO::getSeriesDays, 1);
                    result.setDay(1);
                } else {
                    daysPO = mProductSeriesRechargeDaysDAO.findOne(MProductSeriesRechargeDaysPO::getSeriesDays, detailPO.getRechargeDay() + 1);
                    result.setDay(daysPO.getSeriesDays());
                    result.setRechargeRecordId(latestOne.getId());
                }
                result.setId(daysPO.getId());
                result.setMoney(daysPO.getMoney());
            } else if (DateUtil.days(detailPO.getCreateTime().toLocalDate(), LocalDate.now()) == 0) {
                result.setDay(detailPO.getRechargeDay());
                result.setAlreadyDay(detailPO.getRechargeDay());
                result.setMoney(detailPO.getMoney());
                result.setRechargeRecordId(latestOne.getId());
                result.setAlreadyRecharge(Boolean.TRUE);
            } else {
                MProductSeriesRechargeDaysPO daysPO = mProductSeriesRechargeDaysDAO.findOne(MProductSeriesRechargeDaysPO::getSeriesDays, 1);
                result.setDay(1);
                result.setMoney(daysPO.getMoney());
                result.setId(daysPO.getId());
            }
        }
        List<RechargeDaysVO> rechargeVO = new ArrayList<>();
        daysPOS.forEach(dayPO -> {
            RechargeDaysVO vo = new RechargeDaysVO();
            BeanUtils.copyProperties(dayPO, vo);
            if (Objects.nonNull(result.getRechargeRecordId())) {
                MRecordSeriesRechargeDetailPO po = mRecordSeriesRechargeDetailDAO.findOne(currentUser.getUserId(), result.getRechargeRecordId(), dayPO.getSeriesDays());
                if (Objects.nonNull(po)) {
                    vo.setSeriesDays(po.getRechargeDay());
                    vo.setAlreadyRecharge(Boolean.TRUE);
                    vo.setPinecone(po.getPinecone());
                }
            }
            rechargeVO.add(vo);
        });
        result.setRechargeVOS(rechargeVO);
        if (Objects.isNull(result.getAlreadyDay())) {
            result.setAlreadyDay(result.getDay() - 1);
        }
        RechargeBoxVO boxVO = new RechargeBoxVO();
        if (Objects.nonNull(result.getRechargeRecordId())) {
            BeanUtils.copyProperties(latestOne, boxVO);
        } else {
            List<MProductSeriesRechargeBoxPO> configs = mProductSeriesRechargeBoxDAO.findAll(MProductSeriesRechargeBoxPO::getSeriesDays, Boolean.TRUE);
            boxVO.setThreePrize(configs.get(0).getPinecone());
            boxVO.setFivePrize(configs.get(1).getPinecone());
            boxVO.setSevenPrize(configs.get(2).getPinecone());
            boxVO.setThreeStatus(TaskStatusEnum.go_complete.getCode());
            boxVO.setFiveStatus(TaskStatusEnum.go_complete.getCode());
            boxVO.setSevenStatus(TaskStatusEnum.go_complete.getCode());
        }
        result.setBoxVO(boxVO);
        return Result.success().data(result).build();
    }

    @Override
    public Result<LookOrLockVO> forbidLookProduct() {
        AppUser currentUser = ApiContext.getCurrentUser();
        MProductLookPO lookPO = mProductLookDAO.findEnableOne(EquityEnum.forbid_look.getCode());
        if (Objects.isNull(lookPO)) {
            return Result.failure().message("商品维护中").build();
        }
        MProductLookDetailPO detailPO = mProductLookDetailDAO.findOne(MProductLookDetailPO::getLookId, lookPO.getId());
        LookOrLockVO vo = new LookOrLockVO();
        vo.setId(detailPO.getId());
        vo.setDuration(detailPO.getDuration());
        vo.setMoney(detailPO.getMoney());
        UAppUserEquityPO userEquityPO = uAppUserEquityDAO.findOne(UAppUserEquityPO::getUserId, currentUser.getUserId());
        vo.setEquityNum(userEquityPO.getForbidLookThirty());
        return Result.success().data(vo).build();
    }

    @Override
    public Result<List<LookOrLockVO>> lockProductList() {
        AppUser currentUser = ApiContext.getCurrentUser();
        MProductLookPO lookPO = mProductLookDAO.findEnableOne(EquityEnum.lock_machine.getCode());
        if (Objects.isNull(lookPO)) {
            return Result.failure().message("商品维护中").build();
        }
        UAppUserEquityPO userEquityPO = uAppUserEquityDAO.findOne(UAppUserEquityPO::getUserId, currentUser.getUserId());
        List<MProductLookDetailPO> detailPOS = mProductLookDetailDAO.findList(MProductLookDetailPO::getLookId, lookPO.getId(), MProductLookDetailPO::getDuration, Boolean.TRUE);
        List<LookOrLockVO> vos = ListUtil.copyList(detailPOS, LookOrLockVO.class);
        vos.forEach(vo -> {
            if (vo.getDuration().equals(15)) {
                vo.setEquityNum(userEquityPO.getLockFifteen());
            } else if (vo.getDuration().equals(30)) {
                vo.setEquityNum(userEquityPO.getLockThirty());
            } else if (vo.getDuration().equals(60)) {
                vo.setEquityNum(userEquityPO.getLockSixty());
            }
        });
        return Result.success().data(vos).build();
    }

    @Override
    @Transactional
    public Result<Boolean> getSeriesRechargeBox(BoxDTO param) {
        MRecordSeriesRechargePO po = mRecordSeriesRechargeDAO.findById(param.getRechargeRecordId());
        if (Objects.isNull(po)) {
            return Result.failure().message("记录不存在").build();
        }
        AppUser currentUser = ApiContext.getCurrentUser();
        if (!currentUser.getUserId().equals(po.getUserId())) {
            return Result.failure().message("您不可领取别人的宝箱").build();
        }
        List<Integer> list = Arrays.asList(3, 5, 7);
        if (!list.contains(param.getDay())) {
            return Result.failure().message("无此宝箱可领取").build();
        }
        if (param.getDay() == 3 && !po.getThreeStatus().equals(TaskStatusEnum.unclaimed.getCode())) {
            return Result.failure().message("此宝箱不可领取").build();
        }
        if (param.getDay() == 5 && !po.getFiveStatus().equals(TaskStatusEnum.unclaimed.getCode())) {
            return Result.failure().message("此宝箱不可领取").build();
        }
        if (param.getDay() == 7 && !po.getSevenStatus().equals(TaskStatusEnum.unclaimed.getCode())) {
            return Result.failure().message("此宝箱不可领取").build();
        }
        Integer pinecone;
        if (param.getDay() == 3) {
            po.setThreeStatus(TaskStatusEnum.received_already.getCode());
            uAppUserEquityDAO.addPinecone(currentUser.getUserId(), po.getThreePrize());
            pinecone = po.getThreePrize();
        } else if (param.getDay() == 5) {
            po.setFiveStatus(TaskStatusEnum.received_already.getCode());
            uAppUserEquityDAO.addPinecone(currentUser.getUserId(), po.getFivePrize());
            pinecone = po.getFivePrize();
        } else {
            po.setSevenStatus(TaskStatusEnum.received_already.getCode());
            uAppUserEquityDAO.addPinecone(currentUser.getUserId(), po.getSevenPrize());
            pinecone = po.getSevenPrize();
        }
        mRecordSeriesRechargeDAO.updateById(po);
        DDetailsPineconePO myDetail = new DDetailsPineconePO();
        myDetail.setUserId(currentUser.getUserId());
        myDetail.setLabelType(LabelTypeEnum.series_recharge_box.getCode());
        myDetail.setDetailsType(DetailsTypeEnum.income.getCode());
        myDetail.setPinecone(pinecone);
        myDetail.setRemark("领取ID：" + param.getRechargeRecordId() + "的第" + param.getDay() + "天宝箱");
        dDetailsPineconeDAO.save(myDetail);
        return Result.success().data(Boolean.TRUE).build();
    }
}
